﻿using F29ServerProcess.Interfaces;
using F29ServerProcess.Models;
using IotContract.Dtos.Clients;
using IotContract.Dtos.Servers.Process;
using IotContract.Dtos.Servers.Process.F29;
using IotContract.Dtos.Servers.Pushs;
using IotContract.Enums;
using IotContract.Extensions;
using IotContract.Interfaces;
using IotContract.Interfaces.Process;
using IotContract.Models.Jobs;
using IotContract.Models.Jobs.F29;
using IotContract.Models.Writes.F29;
using Mapster;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XT.Common.Enums;
using XT.Common.Extensions;
using XT.Common.Services;

namespace F29ServerProcess.DataProcess;
/// <summary>
/// 堆垛机处理程序
/// </summary>
public class StackerDataProcess : IServerProcessHandle
{
    public string ProcessName { get; set; } = F29ServerConst.ProcessName;
    public IotEquipType ProcessType { get; set; } = IotEquipType.STACKER;

    private readonly IServerMainManager _mainProcess;
    private readonly IProcessDataService _processDataService;
    private readonly IProcessJobService _processJobService;
    private readonly IEquipValidateService _equipValidateService;
    private readonly ILogService _logService;

    public StackerDataProcess(IServerMainManager serverMainManager,IEquipValidateService equipValidateService, IProcessDataService processDataService,IProcessJobService processJobService, ILogService logService)
    {
        _mainProcess = serverMainManager;
        _processDataService = processDataService;
        _processJobService = processJobService;
        _equipValidateService = equipValidateService;
        _logService = logService;
    }

    public async Task<bool> ParsingData()
    {
        try
        {
            // 获取数据
            var equips = await _mainProcess.GetEquips<PushSiemensS7Dto>(new IotContract.Models.Clients.ClientRequestCommand
            {
                RequestType = IotEquipType.STACKER.ToString(),
                ProtobufType = IotProtobufType.SIEMENS_S7.ToString()
            });


            var scUnitDic = _processDataService.ScUnits;
            // 堆垛机点位不需要设置UnitNum
            Parallel.ForEach(equips, equip =>
            {
                var tags = equip.Tags;
                F29ScUnitDto scUnit = null;
                if (scUnitDic.ContainsKey(equip.Num))
                {
                    scUnit = scUnitDic[equip.Num];
                   
                }
                else
                {
                    scUnit = new F29ScUnitDto();                
                  
                    scUnitDic.TryAdd(equip.Num, scUnit);
                }
                scUnit.EquipNum = equip.Num;
                scUnit.UnitNum = equip.UnitNum;
                scUnit.EquipId = equip.Id;
                scUnit.Connection = equip.Connection;
                SetUnitTag(scUnit, tags);
            });
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.ToString());
        }

        return true;
    }

    /// <summary>
    /// 取值
    /// </summary>
    /// <param name="scUnit"></param>
    /// <param name="tags"></param>
    private void SetUnitTag(F29ScUnitDto scUnit, List<PushEquipTag> tags)
    {
        scUnit.Tags = tags;
        Parallel.ForEach(scUnit.Tags, tag =>
        {
            int.TryParse(tag.Value, out int result);
            switch (tag.TagProperty)
            {
                case "ERROR":
                    {
                        scUnit.Error = result;
                        break;
                    }
                case "MODE":
                    {
                        scUnit.Mode = result;
                        scUnit.ReadTime = tag.ReadTime;
                        break;
                    }
                case "POWER":
                    {
                        scUnit.Power = result;
                        break;
                    }
                case "SEND_END2":
                    {

                        scUnit.SendEnd2 = result;
                        break;
                    }
                case "ACTION":
                    {
                        scUnit.Action = result;
                        break;
                    }
                case "READY":
                    {
                        scUnit.Ready = result;
                        break;
                    }
                case "SEND_END":
                    {
                        scUnit.SendEnd = result;
                        break;
                    }
                case "FIRE":
                    {

                        scUnit.Fire = result;
                        break;
                    }
                case "CAN_POKE2":
                    {

                        scUnit.CanPoke2 = result;
                        break;
                    }
                case "EXIST_TRAY2":
                    {

                        scUnit.ExistTray2 = result;
                        break;
                    }
                case "CAN_POKE":
                    {
                        scUnit.CanPoke = result;
                        break;
                    }
                case "EXIST_TRAY":
                    {

                        scUnit.ExistTray = result;
                        break;
                    }
                case "POKE_USE":
                    {
                        scUnit.PokeUse = result;
                        break;
                    }
                case "FROM_X":
                    {
                        scUnit.FromX = result;
                        break;
                    }
                case "FROM_Y":
                    {
                        scUnit.FromY = result;
                        break;
                    }
                case "FROM_Z":
                    {

                        scUnit.FromZ = result;
                        break;
                    }
                case "TO_X":
                    {

                        scUnit.ToX = result;
                        break;
                    }
                case "TO_Y":
                    {

                        scUnit.ToY = result;
                        break;
                    }
                case "TO_Z":
                    {
                        scUnit.ToZ = result;
                        break;
                    }
                case "TRAY":
                    {
                        scUnit.Tray = tag.Value;
                        break;
                    }
                case "TRAY2":
                    {
                        scUnit.Tray2 = tag.Value;
                        break;
                    }
                case "FROM_X2":
                    {
                        scUnit.FromX2 = result;
                        break;
                    }
                case "FROM_Y2":
                    {
                        scUnit.FromY2 = result;
                        break;
                    }
                case "FROM_Z2":
                    {
                        scUnit.FromZ2 = result;
                        break;
                    }
                case "RIGHT_TRAY":
                    {
                        scUnit.RightTray = tag.Value;
                        break;
                    }
                case "RIGHT_TRAY2":
                    {
                        scUnit.RightTray2 = tag.Value;
                        break;
                    }
                case "W_SEND_END":
                    {
                        scUnit.W_SendEnd = result;
                        break;
                    }
                case "W_RESET":
                    {
                        scUnit.W_Reset = result;
                        break;
                    }
                case "W_SEND":
                    {
                        scUnit.W_Send = result;
                        break;
                    }
                case "W_FROM_X":
                    {
                        scUnit.W_FromX = result;
                        break;
                    }
                case "W_FROM_Y":
                    {
                        scUnit.W_FromY = result;
                        break;
                    }
                case "W_FROM_Z":
                    {
                        scUnit.W_FromZ = result;
                        break;
                    }
                case "W_TO_X":
                    {
                        scUnit.W_ToX = result;
                        break;
                    }
                case "W_TO_Y":
                    {
                        scUnit.W_ToY = result;
                        break;
                    }
                case "W_TO_Z":
                    {
                        scUnit.W_ToZ = result;
                        break;
                    }
                case "W_TRAY":
                    {
                        scUnit.W_Tray = tag.Value;
                        break;
                    }
                case "W_TRAY2":
                    {
                        scUnit.W_Tray2 = tag.Value;
                        break;
                    }
                case "W_POKE_USE":
                    {
                        scUnit.W_PokeUse = result;
                        break;
                    }
                case "W_FROM_X2":
                    {
                        scUnit.W_FromX2 = result;
                        break;
                    }
                case "W_FROM_Y2":
                    {
                        scUnit.W_FromY2 = result;
                        break;
                    }
                case "W_FROM_Z2":
                    {
                        scUnit.W_FromZ2 = result;
                        break;
                    }
                case "W_TO_X2":
                    {
                        scUnit.W_ToX2 = result;
                        break;
                    }
                case "W_TO_Y2":
                    {
                        scUnit.W_ToY2 = result;
                        break;
                    }
                case "W_TO_Z2":
                    {
                        scUnit.W_ToZ2 = result;
                        break;
                    }
                case "W_RIGHT_TRAY":
                    {
                        scUnit.W_RightTray = tag.Value;
                        break;
                    }
                case "W_RIGHT_TRAY2":
                    {
                        scUnit.W_RightTray2 = tag.Value;
                        break;
                    }


            }
        });
    }

    public async Task<bool> ProcessData()
    {
        return true;
    }

    public async Task<bool> ProcessOrder()
    {

        // 入库
        await OrderEnter();

        // 出库
        await OrderOut();

        // 移库
        await OrderMove();

        // 火警
        await OrderFire();

        // 容错
        // await OrderRun();

        return true;
       
    }


    #region 调度逻辑

    #region 入库
    /// <summary>
    /// 控制入库
    /// </summary>
    /// <returns></returns>
    private async Task OrderEnter()
    {

        // 根据设备分组
        var enterJobs = _processJobService.EnterJobs;

        foreach (var sc in enterJobs.Keys)
        {
            var jobs = enterJobs[sc];
            if (jobs != null && jobs.Count > 0)
            {
                var job= jobs.Values.OrderBy(x => x.CreateTime).FirstOrDefault();
                // 未启动
                if (job.Status == 0)
                {
                    // 如果存在火警任务，先不进行入库
                    var hasFire = _processJobService.FireJobs.ContainsKey(job.EquipNum);

                    if (hasFire)
                    {
                        continue;
                    }

                    await ScRunEnter(job);
                }
                // 正在运行中，运行完成后提交数据
                else if (job.Status == 1)
                {
                    await ScEnterComplete(job);
                }
                // 运行完成，写入W_SEND_END
                // 运行完成，写入W_SEND_END
                else if (job.Status == 2)
                {





                    if (job.Message != "Skip" && job.ErrorMsg.IsNullOrEmpty())
                    {
                        if (job.Message != "Skip" && job.ErrorMsg.IsNullOrEmpty())
                        {
                            var result = await _processDataService.CompleteJob(job.JobID, job.JobID2);
                            if (!result.Success)
                            {
                                job.ErrorMsg = result.Message;
                            }



                        }
                        if (job.ErrorMsg.IsNullOrEmpty())
                        {
                            _processJobService.RemoveJob(job, ProcessProviderType.EnterJob);
                        }
                    }





                }
            }
        }


    }

    /// <summary>
    /// 入库启动
    /// </summary>
    /// <param name="job"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    private async Task ScRunEnter(F29EnterJob job)
    {
        try
        {
            if(job.JobID.IsNotNullOrEmpty() && job.FromTagNumber>0)
            {
                var tag1 = _processDataService.CvUnitTags.GetValueOrDefault(job.FromTagNumber);        
                // 不允许取货
                if (tag1.AllowEnter == 0)
                {
                    return;
                }
            }

            // 双叉任务
            if (job.JobID2.IsNotNullOrEmpty() && job.FromTagNumber2>0)
            {
                var tag2 = _processDataService.CvUnitTags.GetValueOrDefault(job.FromTagNumber2);

             
                // 不允许取货
                if (tag2.AllowEnter == 0)
                {
                    return;
                }


            }
            var sctag = _processDataService.ScUnits.GetValueOrDefault(job.EquipNum);

            if (!_equipValidateService.ValidateStacker(sctag))
            {
                return;
            }
            

            
            // 找到相同堆垛机出库任务，比较时间和调度顺序
            var outQuene = _processJobService.OutJobs.GetValueOrDefault(job.EquipNum);
            if (outQuene != null && outQuene.Count > 0)
            {
                var outJob= outQuene.Values.OrderBy(x => x.CreateTime).FirstOrDefault(x=>x.Status==0 && x.ErrorMsg.IsNotNullOrEmpty());
                if (outJob != null)
                {
                    // 刚刚进行过入库，优先出库
                    if (sctag.ActionType == ProcessProviderType.EnterJob)
                    {
                        return;
                    }
                    // 出库时间小于入库，优先出库
                    if (outJob.CreateTime < job.CreateTime)
                    {
                        return;
                    }
                }
            }



            var dicKey = job.GetKey();

            // 向FMS验证JOB
       

            var scWrite = job.Adapt<F29ScPlcWrite>();
           
            var result = await _processDataService.WriteSCToRun(scWrite, sctag.EquipNum);

            if (!result)
            {
                job.ErrorMsg = "Write SC Error,Please Reset Enter CV";
                // 写入失败
                return;
            }



            //任务赋值
            sctag.JobID = job.JobID;

            job.RunTime = DateTime.Now;

            job.ErrorMsg = "";
            // 已经启动
            job.Status = 1;

            // 进行入库
            sctag.ActionType = ProcessProviderType.EnterJob;

            await _logService.LogContent($"{job.ToString()} 堆垛机启动入库成功", LogEnum.Info, job.EquipNum.ToString());





            return;
        }
        catch (Exception ex)
        {
            job.ErrorMsg = $"启动失败,{ex.Message}";

            return;
        }
    }
    /// <summary>
    /// 入库执行完成
    /// </summary>
    /// <param name="job"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    private async Task ScEnterComplete(F29EnterJob job)
    {


       
            // 10s内不可能完成
            if (job.RunTime==null || DateTime.Now.Subtract(job.RunTime.Value).TotalSeconds < 10)
            {
                return;
            }
           




          


            var sctag = _processDataService.ScUnits.GetValueOrDefault(job.EquipNum);
            if (sctag == null) return;
            // 超时赋值堆垛机错误码
            if (sctag.Error>0)
            {
                job.ErrorMsg = sctag.Error.ToString();
                 return;
            
            }
            sctag.Rate = (DateTime.Now.Subtract(job.RunTime.Value).TotalSeconds * 100 / 60).To<int>();


            if (sctag.SendEnd == 1  && sctag.W_Tray.IsNotNullOrEmpty() && sctag.Error == 0 )
            {

                if (job.JobID2.IsNotNullOrEmpty()  && sctag.SendEnd2 == 0)
                {
                    //双叉还没有结束
                    return;
                }
            // 堆垛机写入完成
               sctag.Rate = 0;
               bool result= await _processDataService.WriteSCToComplete(sctag.EquipNum);

                if (result)
                {
                    job.Status = 2;
                    sctag.JobID = string.Empty;
                }
            }   
    }
    #endregion

    #region 出库
    /// <summary>
    /// 控制出库
    /// </summary>
    /// <returns></returns>
    private async Task OrderOut()
    {

        
        var outJobs = _processJobService.OutJobs;

        foreach (var sc in outJobs.Keys)
        {
            var jobs = outJobs[sc];
            if (jobs != null && jobs.Count > 0)
            {
                var job = jobs.Values.OrderBy(x => x.CreateTime).FirstOrDefault();
                // 未启动
                if (job.Status == 0)
                {

                    // 如果存在火警任务，先不进行出库
                    var hasFire = _processJobService.FireJobs.ContainsKey(job.EquipNum);

                    if (hasFire)
                    {
                        continue;
                    }

                    await ScRunOut(job);
                }
                // 正在运行中，运行完成后提交数据
                else if (job.Status == 1)
                {
                    await ScOutComplete(job);
                }
              
                // 运行完成，写入W_SEND_END
                else if (job.Status == 2)
                {

                    if (job.Message != "Skip" && job.ErrorMsg.IsNullOrEmpty())
                    {
                        var result = await _processDataService.CompleteJob(job.JobID, job.JobID2);
                        if (!result.Success)
                        {
                            job.ErrorMsg = result.Message;
                        }
                        
                           
                        
                    }
                    if(job.ErrorMsg.IsNullOrEmpty())
                    {
                        _processJobService.RemoveJob(job, ProcessProviderType.OutJob);
                    }

                }
            }
        }


    }
    /// <summary>
    /// 入库启动
    /// </summary>
    /// <param name="job"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    private async Task ScRunOut(F29OutJob job)
    {
        try
        {
            if (job.JobID.IsNotNullOrEmpty() && job.ToTagNumber>0)
            {
                // 放货站台
                var tag = _processDataService.CvUnitTags.GetValueOrDefault(job.ToTagNumber);
              
                // 是否允许出库
                if (tag.AllowOut == 0)
                {
                    return;
                }
            }
            // 双叉任务
            if (job.JobID2.IsNotNullOrEmpty() && job.ToTagNumber2>0)
            {
                var tag2 = _processDataService.CvUnitTags.GetValueOrDefault(job.ToTagNumber2);



                if (tag2.AllowOut == 0)
                {
                    return;
                }


            }

            var sctag = _processDataService.ScUnits.GetValueOrDefault(job.EquipNum);

            if (!_equipValidateService.ValidateStacker(sctag))
            {
                return;
            }
            // 找到相同堆垛机出库任务，比较时间和调度顺序
            // 刚做了出库
            if (sctag.ActionType == ProcessProviderType.OutJob)
            {
                // 找到入库任务
                var enters = _processJobService.EnterJobs.GetValueOrDefault(job.EquipNum);
                var moves = _processJobService.MoveJobs.GetValueOrDefault(job.EquipNum);
                if(enters!=null && enters.Count > 0)
                {
                    var enterJob = enters.Values.OrderBy(x => x.CreateTime).FirstOrDefault(x => x.Status == 0 && x.ErrorMsg.IsNotNullOrEmpty());
                    if(enterJob != null)
                    {
                        // 入库任务在前
                        if (enterJob.CreateTime < job.CreateTime)
                        {
                            return;
                        }
                    }
                }

                if (moves != null && moves.Count > 0)
                {
                    var moveJob = moves.Values.OrderBy(x => x.CreateTime).FirstOrDefault(x => x.Status == 0 && x.ErrorMsg.IsNotNullOrEmpty());
                    if (moveJob != null)
                    {
                        // 移库任务在前
                        if (moveJob.CreateTime < job.CreateTime)
                        {
                            return;
                        }
                    }
                }


              
            }


          



            var dicKey = job.GetKey();

          
            // 获取FMS任务进行对比         

            var scWrite = job.Adapt<F29ScPlcWrite>();
           
            var result = await _processDataService.WriteSCToRun(scWrite, sctag.EquipNum);

            if (!result)
            {
                job.ErrorMsg = "Write SC Error";
                // 写入失败
                return;
            }



            //任务赋值
            sctag.JobID = job.JobID;

            job.RunTime = DateTime.Now;

            job.ErrorMsg = "";
            // 已经启动
            job.Status = 1;

            // 进行出库
            sctag.ActionType = ProcessProviderType.OutJob;

            await _logService.LogContent($"{job.ToString()} 堆垛机启动出库成功", LogEnum.Info, job.EquipNum.ToString());





            return;
        }
        catch (Exception ex)
        {
            job.ErrorMsg = $"启动失败,{ex.Message}";

            return;
        }
    }
    /// <summary>
    /// 出库执行完成
    /// </summary>
    /// <param name="job"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    private async Task ScOutComplete(F29OutJob job)
    {

        try
        {
            // 10s内不可能完成
            if (job.RunTime==null ||  DateTime.Now.Subtract(job.RunTime.Value).TotalSeconds < 10)
            {
                return;
            }
         
            string dicKey = job.GetKey();
            var sctag = _processDataService.ScUnits.GetValueOrDefault(job.EquipNum);
            if (sctag == null) return;
           
            if (sctag.Error>0)
            {
                job.ErrorMsg = sctag.Error.ToString();
                return;
            }
            sctag.Rate = (DateTime.Now.Subtract(job.RunTime.Value).TotalSeconds * 100 / 60).To<int>();

            if (sctag.SendEnd == 1  && sctag.W_Tray.IsNotNullOrEmpty() && sctag.Error == 0)
            {

                if (job.JobID2.IsNotNullOrEmpty()  && sctag.SendEnd2 == 0)
                {
                    //双叉还没有结束
                    return;
                }
                sctag.Rate = 0;
                var result = await _processDataService.WriteSCToComplete(sctag.EquipNum);

                if (job.ToTagNumber > 0)
                {
                    await _processDataService.WriteCvStatus(job.ToTagNumber, 1);
                }
                if (job.ToTagNumber2 > 0)
                {
                    await _processDataService.WriteCvStatus(job.ToTagNumber2, 1);
                }
                if (result)
                {
                    
                    job.Status = 2;
                    sctag.JobID = string.Empty;
                }

            }
        }
        catch (Exception ex)
        {
            await _logService.LogContent($"{job.ToString()} 堆垛机出库任务 刷新数据失败，{ex.Message}", LogEnum.Error, job.EquipNum.ToString());

        }
    }
    #endregion

    #region 移库
    /// <summary>
    /// 控制移库
    /// </summary>
    /// <returns></returns>
    private async Task OrderMove()
    {


        var moveJobs = _processJobService.MoveJobs;

        foreach (var sc in moveJobs.Keys)
        {
            var jobs = moveJobs[sc];
            if (jobs != null && jobs.Count > 0)
            {
                var job = jobs.Values.OrderBy(x => x.CreateTime).FirstOrDefault();
                // 未启动
                if (job.Status == 0)
                {

                    // 如果存在火警任务，先不进行移库
                    var hasFire = _processJobService.FireJobs.ContainsKey(job.EquipNum);

                    if (hasFire)
                    {
                        continue;
                    }

                    await ScRunMove(job);
                }
                // 正在运行中，运行完成后提交数据
                else if (job.Status == 1)
                {
                    await ScMoveComplete(job);
                }
                // 运行完成，写入W_SEND_END
                else if (job.Status == 2)
                {

                    if (job.Message != "Skip" && job.ErrorMsg.IsNullOrEmpty())
                    {
                        var result = await _processDataService.CompleteJob(job.JobID, "");
                        if (!result.Success)
                        {
                            job.ErrorMsg = result.Message;
                        }



                    }
                    if (job.ErrorMsg.IsNullOrEmpty())
                    {
                        _processJobService.RemoveJob(job, ProcessProviderType.MoveJob);
                    }

                }
            }
        }


    }
    /// <summary>
    /// 移库启动
    /// </summary>
    /// <param name="job"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    private async Task ScRunMove(F29MoveJob job)
    {
        try
        {
            
            var sctag = _processDataService.ScUnits.GetValueOrDefault(job.EquipNum);

            if (!_equipValidateService.ValidateStacker(sctag))
            {
                return;
            }
            // 找到相同堆垛机出库任务，比较时间和调度顺序

            // 找到入库任务
            var enters = _processJobService.EnterJobs.GetValueOrDefault(job.EquipNum);
                var outs = _processJobService.OutJobs.GetValueOrDefault(job.EquipNum);
                if (enters != null && enters.Count > 0)
                {
                    var enterJob = enters.Values.OrderBy(x => x.CreateTime).FirstOrDefault(x => x.Status == 0 && x.ErrorMsg.IsNotNullOrEmpty());
                    if (enterJob != null)
                    {
                        // 入库任务在前
                        if (enterJob.CreateTime < job.CreateTime)
                        {
                            return;
                        }
                    }
                }

                if (outs != null && outs.Count > 0)
                {
                    var outJob = outs.Values.OrderBy(x => x.CreateTime).FirstOrDefault(x => x.Status == 0 && x.ErrorMsg.IsNotNullOrEmpty());
                    if (outJob != null)
                    {
                        // 出库任务在前
                        if (outJob.CreateTime < job.CreateTime)
                        {
                            return;
                        }
                    }
                }



            






            var dicKey = job.GetKey();

           
           

            var scWrite = job.Adapt<F29ScPlcWrite>();
           
            var result = await _processDataService.WriteSCToRun(scWrite, sctag.EquipNum);

            if (!result)
            {
                job.ErrorMsg = "Write SC Error";
                // 写入失败
                return;
            }



            //任务赋值
            sctag.JobID = job.JobID;

            job.RunTime = DateTime.Now;

            job.ErrorMsg = "";
            // 已经启动
            job.Status = 1;

            // 进行移库
            sctag.ActionType = ProcessProviderType.MoveJob;

            await _logService.LogContent($"{job.ToString()} 堆垛机开始移库成功", LogEnum.Info, job.EquipNum.ToString());





            return;
        }
        catch (Exception ex)
        {
            job.ErrorMsg = $"启动失败,{ex.Message}";

            return;
        }
    }
    /// <summary>
    /// 移库执行完成
    /// </summary>
    /// <param name="job"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    private async Task ScMoveComplete(F29MoveJob job)
    {


            // 10s内不可能完成
            if (job.RunTime == null || DateTime.Now.Subtract(job.RunTime.Value).TotalSeconds < 10)
            {
                return;
            }
       

            var sctag = _processDataService.ScUnits.GetValueOrDefault(job.EquipNum);
            if (sctag == null) return;
            // 超时赋值堆垛机错误码
            if (sctag.Error>0)
            {
                job.ErrorMsg = sctag.Error.ToString();
                return;
            }

        sctag.Rate = (DateTime.Now.Subtract(job.RunTime.Value).TotalSeconds * 100 / 60).To<int>();

        if (sctag.SendEnd == 1  && sctag.W_Tray.IsNotNullOrEmpty() && sctag.Error == 0)
            {
                sctag.Rate = 0;
                var result = await _processDataService.WriteSCToComplete(sctag.EquipNum);

                if (result)
                {
                    job.Status = 2;
                    sctag.JobID = string.Empty;
                }

                // 联动充放电

            }
          



     
    }
    #endregion

    #region 火警
    /// <summary>
    /// 控制火警
    /// </summary>
    /// <returns></returns>
    private async Task OrderFire()
    {


        var fireJobs = _processJobService.FireJobs;

        foreach (var sc in fireJobs.Keys)
        {
            var jobs = fireJobs[sc];
            if (jobs != null && jobs.Count > 0)
            {
                var job = jobs.Values.OrderBy(x => x.CreateTime).FirstOrDefault();
                // 未启动
                if (job.Status == 0)
                {
                    await ScRunFire(job);
                }
                // 正在运行中，运行完成后提交数据
                else if (job.Status == 1)
                {
                    await ScFireComplete(job);
                }
                // 运行完成，写入W_SEND_END
                else if (job.Status == 2)
                {

                    if (job.Message != "Skip")
                    {
                        var result = await _processDataService.CompleteJob(job.JobID, "");
                        if (!result.Success)
                        {
                            job.ErrorMsg = result.Message;
                        }
                    }

                    if (job.ErrorMsg.IsNullOrEmpty()) _processJobService.RemoveJob(job, ProcessProviderType.EnterJob);

                    job.Status = 3;

                }

            }
        }


    }
    /// <summary>
    /// 入库启动
    /// </summary>
    /// <param name="job"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    private async Task ScRunFire(F29MoveJob job)
    {
        try
        {
            var sctag = _processDataService.ScUnits.GetValueOrDefault(job.EquipNum);

            if (!_equipValidateService.ValidateStacker(sctag)) return;

            // 如果存在任务，返回
            if (sctag == null || sctag.JobID.IsNotNullOrEmpty()) return;
            // 找到相同堆垛机出库任务，比较时间和调度顺序

           










          


            // 查询FMS job的状态，确认是否运行
            //var scRemote = await _remoteHttpService.GetScRemoteTask(job.JobID);
            //if (scRemote.Data == null && scRemote.Code == 100)
            //{
            //    return;
            //}
            //if (scRemote.Data == null)
            //{
            //    // await _serverDataService.RemoveEnterJob(job);
            //    job.ErrorMsg = IotMsgConst.ScEnterRemoteError;
            //    job.IsError = 888;
            //    return false;
            //}
            //else if (scRemote.Data.TaskStatus != 1)
            //{
            //    job.ErrorMsg = $"{IotMsgConst.ScEnterRemoteError} {scRemote.Data.TaskStatus}";
            //    job.IsError = 888;
            //    return false;
            //}
            //job.Data = string.Join(',', scRemote.Data.TrayNos.Where(x => x.IsNotNullOrEmpty()));

            var scWrite = job.Adapt<F29ScPlcWrite>();
         
            var result = await _processDataService.WriteSCToRun(scWrite, sctag.EquipNum);

            if (!result)
            {
                job.ErrorMsg = "Write SC Error";
                // 写入失败
                return;
            }



            //任务赋值
            sctag.JobID = job.JobID;

            job.RunTime = DateTime.Now;

            job.ErrorMsg = "";
            // 已经启动
            job.Status = 1;

            // 进行火警
            sctag.ActionType = ProcessProviderType.FireJob;

            await _logService.LogContent($"{job.ToString()} 堆垛机开始火警移库成功", LogEnum.Info, job.EquipNum.ToString());





            return;
        }
        catch (Exception ex)
        {
            job.ErrorMsg = $"启动失败,{ex.Message}";

            return;
        }
    }
    /// <summary>
    /// 入库执行完成
    /// </summary>
    /// <param name="job"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    private async Task ScFireComplete(F29MoveJob job)
    {

       
            // 10s内不可能完成
            if (job.RunTime == null || DateTime.Now.Subtract(job.RunTime.Value).TotalSeconds < 10)
            {
                return;
            }
            var tag = _processDataService.CvUnitTags.GetValueOrDefault(job.ToTagNumber);




            string dicKey = job.GetKey();




            var sctag = _processDataService.ScUnits.GetValueOrDefault(job.EquipNum);
            if (sctag == null) return;
            // 超时赋值堆垛机错误码
            if (job.CreateTime != null && DateTime.Now.Subtract(job.CreateTime.Value).TotalMinutes > 2)
            {
                job.ErrorMsg = sctag.Error.ToString();
            }


            if (sctag.SendEnd == 1  && sctag.W_Tray.IsNotNullOrEmpty() && sctag.Error == 0 && tag.Error == 0)
            {




                var result = await _processDataService.WriteSCToComplete(sctag.EquipNum);
                if (result)
                {
                    job.Status = 2;
                }
                // 联动充放电

                //开任务进行回调
                


            }
            else if(sctag.SendEnd==0 && job.Status == 2)
            {
                job.Status = 3;
            }




        
      
    }
    #endregion


    #endregion

    public async Task<bool> ProcessWarn()
    {
       
        return true;
    }

    public bool Stop()
    {
        _processDataService.ScUnits.Clear();
        return true;
    }
}
